<?php

namespace App\Console\Commands;

use App\Library\Logger;
use App\Models\PollingPlan\Log;
use App\Repositories\PollingPlanRepo;
use App\Repositories\PollingRepo;
use Carbon\Carbon;
use Illuminate\Console\Command;

class PollingPlan extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'polling_plan:generate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '执行巡检计划';

    private $logger;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
        $this->logger = new Logger('polling_plan/generate');
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function handle()
    {
        $bench = new \Ubench();
        $bench->start();

        $this->action();

        $bench->end();
        $this->logger->debug("time used: " . $bench->getTime());
        $this->logger->debug("memory used: " . $bench->getMemoryUsage());
    }

    /**
     * 根据巡检任务创建巡检计划
     *  排除未到开始时间和已过截止时间的计划
     *  重复周期
     *      天: 每隔 * 天创建任务
     *      周: 每周星期* 创建任务
     *      月: 每月*号 创建任务
     *  未开始
     *      直接创建
     *  已开始
     *      查看创建的最后一条记录，根据记录查询到生成的日期，再根据规则选择是否创建新记录
     *  未开始
     *      直接创建
     * @return void
     */
    private function action()
    {
        $this->checkStatus();
        $now = Carbon::now()->toDateTimeString();
        $plans = \App\Models\PollingPlan::query()
            ->where('plan_start_at', '<=', $now)
            ->where('plan_end_at', '>=', $now)
            ->whereIn('status', [PollingPlanRepo::STATUS_CREATE, PollingPlanRepo::STATUS_START])
            ->get();
        if (!$plans->count()) {
            $this->logger->info("暂无需要创建任务的的巡检计划");
            return;
        }
        foreach ($plans as $plan) {
            $planId = $plan->id;
            $planStatus = $plan->status;
            $pollingCircleUnit = $plan->circle_unit;
            $pollingCircleCount = $plan->circle_count;
            /**
             * 已开始: 查看创建记录，选择是否创建新纪录
             */
            if ($planStatus == PollingPlanRepo::STATUS_START) {
                $pollingLatest = Log::byPollingPlanId($planId)->byLatest()->first();
                if (empty($pollingLatest)) {
                    $this->createPlan($plan);
                } else {
                    $logCreateTime = Carbon::parse($pollingLatest->create_time)->toDateTimeString();
                    // 最近一次创建时间
                    $logCreateTime = Carbon::parse($logCreateTime)->toDateString();
                    // 没有到创建时间时，直接略过
                    /**
                     *      天: 每隔 * 天创建任务
                     *      周: 每周星期* 创建任务
                     *      月: 每月*号 创建任务
                     */
                    if ($pollingCircleUnit == PollingPlanRepo::CIRCLE_UINT_DAY) {
                        // 下次创建时间
                        $nextCreateTime = Carbon::parse($logCreateTime)->addDays($pollingCircleCount)->toDateString();
                        $currentTime = Carbon::now()->toDateString();
                        // 当前时间 <= 下次创建时间
                        if ($currentTime != $nextCreateTime) {
                            $this->logger->info("计划ID: {$planId} 已跳过，原因: 未到创建时间. 本次创建时间: {$nextCreateTime}, 当前时间: {$currentTime}");
                            continue;
                        }
                    }
                    if ($pollingCircleUnit == PollingPlanRepo::CIRCLE_UNIT_WEEK) {
                        if ($pollingCircleCount < 1) {
                            $pollingCircleCount = 1;
                        } elseif ($pollingCircleCount > 7) {
                            $pollingCircleCount = 7;
                        }
                        $current = Carbon::now()->toDateTimeString();
                        if ($logCreateTime >= $current) {
                            $this->logger->info("计划ID: {$planId} 已跳过，原因: 未到创建时间. 最近一次创建时间: {$logCreateTime}, 当前时间: {$current}");
                        }
                        // 获取当前星期几
                        $currentWeekDay = Carbon::now()->dayOfWeek;
                        if ($currentWeekDay != $pollingCircleCount) {
                            $this->logger->info("计划ID: {$planId} 已跳过，原因: 未到创建时间. 应创建时间: 星期{$pollingCircleCount}, 当前时间: 星期{$currentWeekDay}");
                            continue;
                        }
                    }
                    if ($pollingCircleUnit == PollingPlanRepo::CIRCLE_UNIT_MONTH) {
                        // 本月
                        $currentCalculate = Carbon::now()->year . '-' . (Carbon::now()->month > 10 ? Carbon::now()->month : '0' . Carbon::now()->month);
                        // 已创建月份
                        $lastCalculate = Carbon::parse($logCreateTime)->year . '-' . (Carbon::parse($logCreateTime)->month > 10 ? Carbon::parse($logCreateTime)->month : '0' . Carbon::parse($logCreateTime)->month);
                        if ($currentCalculate >= $lastCalculate) {
                            $this->logger->info("计划ID: {$planId} 已跳过，原因: 未到创建月份");
                            continue;
                        }
                        // 当前月份的最后一天的号数
                        $monthLastDay = Carbon::now()->lastOfMonth()->day;
                        if ($pollingCircleCount < 1) {
                            $pollingCircleCount = 1;
                        } elseif ($pollingCircleCount > $monthLastDay) {
                            $pollingCircleCount = $monthLastDay;
                        }
                        $currentMonthDay = Carbon::now()->day;
                        if ($currentMonthDay != $pollingCircleCount) {
                            $this->logger->info("计划ID: {$planId} 已跳过，原因: 未到创建时间. 应创建时间: 星期{$pollingCircleCount}, 当前时间: 星期{$currentWeekDay}");
                            continue;
                        }
                    }
                    $this->createPlan($plan);
                }
            } elseif ($planStatus == PollingPlanRepo::STATUS_CREATE) {
                $this->createPlan($plan);
            }
        }
    }

    /**
     * 变更状态
     * 已到截止时间: -> 已完成
     * 已到开始时间: 未到截止时间: -> 已开始
     *
     * @return void
     */
    private function checkStatus()
    {
        $plans = \App\Models\PollingPlan::query()
            ->where('status', '<>', PollingPlanRepo::STATUS_COMPLETE)
            ->get();
        if (!$plans->count()) {
            return;
        }
        $now = Carbon::now()->toDateString();
        foreach ($plans as $plan) {
            $endAt = Carbon::parse($plan->plan_end_at)->toDateString();
            $startAt = Carbon::parse($plan->plan_start_at)->toDateString();
            if ($endAt <= $now) {
                $plan->status = PollingPlanRepo::STATUS_COMPLETE;
                $plan->saveOrFail();
            } elseif ($startAt <= $now && $now < $endAt) {
                $plan->status = PollingPlanRepo::STATUS_START;
                $plan->saveOrFail();
            }
        }
    }

    private function createPlan($plan)
    {
        $number = PollingRepo::getPollingNumber();
        $type = PollingRepo::CREATE_TASK;
        $status = PollingRepo::STATUS_ASSIGN;

        $pollingCustomerId = $plan->polling_customer_id;
        $main = [
            'number' => $number,
            'type' => $type,
            'status' => $status,
            'customer_id' => $pollingCustomerId,
            'customer_name' => $plan->polling_customer_name,
            'customer_user_id' => $plan->polling_customer_id,
            'customer_user_name' => $plan->polling_customer_user_name,
            'customer_user_telephone' => $plan->polling_customer_user_telephone,
            'customer_address' => $plan->polling_customer_address,
            'plan_at' => $plan->plan_at,
            'description' => $plan->polling_description,
            'user_id' => $plan->polling_user_id,
            'user_name' => $plan->polling_user_name,
            'create_user_id' => 0,
            'create_user_name' => '巡检计划',
            'timeout_hour' => 24,
        ];

        $history = [
            'actor_id' => 0,
            'actor_name' => '巡检计划',
            'status' => $status,
            'to_actor_id' => $plan->polling_user_id,
            'to_actor_name' => $plan->polling_user_name,
            'content' => "把巡检任务 #{$number} 分配给了 " . $plan->polling_user_name ?? ''
        ];

        $data = [
            'main' => $main,
            'history' => $history
        ];

        $newPolling = PollingRepo::storeAction($data);

        $pollingId = $newPolling['id'];

        $log = new Log();
        $log->fill([
            'polling_id' => $pollingId,
            'user_id' => 0,
            'status' => PollingPlanRepo::LOG_STATUS_SUCCESS,
        ]);

        $plan->logs()->save($log);

        $plan->status = PollingPlanRepo::STATUS_START;
        $plan->saveOrFail();
    }
}
